package com.shenzhen.horselive.network;


import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.shenzhen.horselive.App;
import com.shenzhen.horselive.api.TokenInterceptor;

import java.io.File;
import java.io.IOException;
import java.net.Proxy;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;


public class RetrofitClient {


    private static OkHttpClient mOkHttpClient;
    private static boolean debug = true;
    private HashMap<String, Retrofit> mRetrofits;

    private static volatile RetrofitClient instance = null;

    public static RetrofitClient getInstance() {
        if (instance == null) {
            synchronized (RetrofitClient.class) {
                if (instance == null) {
                    instance = new RetrofitClient();
                }
            }
        }
        return instance;
    }


    private RetrofitClient() {
        mRetrofits = new HashMap<>();
        initOkHttpClient();
//        gson = new GsonBuilder().create();
    }

    public static void setDebug(boolean debug) {
        RetrofitClient.debug = debug;
    }


    public Retrofit createRetrofit(String baseUrl) {

        GsonBuilder builder=new GsonBuilder();
        builder.registerTypeAdapter(int.class, new TypeAdapter() {
            @Override
            public void write(JsonWriter out, Object value) {
            }

            @Override
            public Object read(JsonReader in) throws IOException {
                JsonToken jsonToken = in.peek();
                switch (jsonToken) {
                    case NULL:
                        in.nextNull();
                        return null;
                    case NUMBER:
                    case STRING:
                        try {
                            return Integer.parseInt(in.nextString());
                        } catch (NumberFormatException e) {
                            return 0;
                        }
                    default:
                        throw new JsonSyntaxException("Expecting number, got: " + jsonToken);
                }
            }
        });
        Gson gson=builder.create();
        return new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(mOkHttpClient)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    public <T> T create(String baseUrl, Class<T> mClass) {
        if (!mRetrofits.containsKey(baseUrl)) {
            mRetrofits.put(baseUrl, createRetrofit(baseUrl));
        }
        return mRetrofits.get(baseUrl).create(mClass);
    }

    private void initOkHttpClient() {
        if (mOkHttpClient == null) {
            synchronized (OkHttpClient.class) {
                if (mOkHttpClient == null) {
                    // 指定缓存路径,缓存大小100Mb
                    Cache cache = new Cache(new File(App.getInstance().getCacheDir(), "HttpCache"),
                            1024 * 1024 * 100);

                    OkHttpClient.Builder builder = new OkHttpClient.Builder().cache(cache);

//                    builder.addInterceptor(new LogInterceptor(){
//
//                        @Override
//                        public Response intercept(Chain chain) throws IOException {
//
//                            return super.intercept(chain);
//                        }
//                    });
                    //token过期
                    builder.addInterceptor(new TokenInterceptor());

                    builder.addInterceptor(chain -> {
                        Request original = chain.request();
                        Request.Builder requestBuilder = original.newBuilder()
                                .header("Content-Type", "application/json")
                                .header("Accept", "application/json");
//                                .header("appHeader", gson.toJson(new AppHeader()));
                        Request request = requestBuilder
                                .build();

                        return chain.proceed(request);
                    });
                    if (debug) {
                        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                        builder.addInterceptor(interceptor);
                    }
//                    SSLContext ctx = null;
//
//                    try {
//                        ctx = SSLContext.getInstance("SSL");
//                        ctx.init(new KeyManager[0], new TrustManager[]{new TrustAllCertsManager()}, new SecureRandom());
//                    } catch (KeyManagementException | NoSuchAlgorithmException e) {
//                        e.printStackTrace();
//                    }
//
//                    SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();
//                    builder.sslSocketFactory(sslSocketFactory);
                    builder.hostnameVerifier((hostname, session) -> true);

                    mOkHttpClient = builder.retryOnConnectionFailure(true).proxy(Proxy.NO_PROXY)
                            .connectTimeout(15, TimeUnit.SECONDS)
                            .build();
                }
            }
        }
    }

    private static class TrustAllCertsManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }

}
